using System;
using System.Runtime.InteropServices;
using Net.SamuelChen.Libs.WinForm;

namespace Net.SamuelChen.Libs.WinForm.Sys {
	
	#region Class HookEventArgs
	public class HookEventArgs : EventArgs {
		public int HookCode;	// Hook code
		public IntPtr wParam;	// WPARAM argument
		public IntPtr lParam;	// LPARAM argument
	}
	#endregion

	#region Class Hook
	/// <summary>
	/// Summary description for Hooks.
	/// </summary>
	public class Hook {

		// ************************************************************************
		// Filter function delegate
		public delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
		// ************************************************************************

		// ************************************************************************
		// Internal properties
		protected IntPtr m_hhook = IntPtr.Zero;
		protected HookProc m_filterFunc = null;
		protected HookType m_hookType;
		// ************************************************************************
		
		// ************************************************************************
		// Event delegate
		public delegate void HookEventHandler(object sender, HookEventArgs e);
		// ************************************************************************

		// ************************************************************************
		// Event: HookInvoked 
		public event HookEventHandler HookInvoked;
		protected void OnHookInvoked(HookEventArgs e) {
			if (HookInvoked != null)
				HookInvoked(this, e);
		}
		// ************************************************************************

		// ************************************************************************
		// Class constructor(s)
		public Hook(HookType hook) {
			m_hookType = hook;
			m_filterFunc = new HookProc(this.CoreHookProc); 
		}
		public Hook(HookType hook, HookProc func) {
			m_hookType = hook;
			m_filterFunc = func; 
		}		
		// ************************************************************************
	
		// ************************************************************************
		// Default filter function
		protected int CoreHookProc(int code, IntPtr wParam, IntPtr lParam) {
			if (code < 0)
				return CallNextHookEx(m_hhook, code, wParam, lParam);

			// Let clients determine what to do
			HookEventArgs e = new HookEventArgs();
			e.HookCode = code;
			e.wParam = wParam;
			e.lParam = lParam;
			OnHookInvoked(e);

			// Yield to the next hook in the chain
			return CallNextHookEx(m_hhook, code, wParam, lParam);
		}
		// ************************************************************************

		// ************************************************************************
		// Install the hook to current thread
		public void Install() {
			m_hhook = SetWindowsHookEx(
				m_hookType, 
				m_filterFunc, 
				IntPtr.Zero, 
				AppDomain.GetCurrentThreadId());
		}
		// ************************************************************************

		// ************************************************************************
		// Install the hook to specified thread
		public void Install(IntPtr hInstance) {
			m_hhook = SetWindowsHookEx(
				m_hookType, 
				m_filterFunc, 
				hInstance, 
				0);			
		}
		// ************************************************************************

		// ************************************************************************
		// Uninstall the hook
		public void Uninstall() {
			UnhookWindowsHookEx(m_hhook); 
		}
		// ************************************************************************


	#region Win32 Imports
	// ************************************************************************
	// Win32: SetWindowsHookEx()
	[DllImport("user32.dll")]
	protected static extern IntPtr SetWindowsHookEx(HookType code, 
		HookProc func,
		IntPtr hInstance,
		int threadID);
	// ************************************************************************

	// ************************************************************************
	// Win32: UnhookWindowsHookEx()
	[DllImport("user32.dll")]
	protected static extern int UnhookWindowsHookEx(IntPtr hhook); 
	// ************************************************************************

	// ************************************************************************
	// Win32: CallNextHookEx()
	[DllImport("user32.dll")]
	protected static extern int CallNextHookEx(IntPtr hhook, 
		int code, IntPtr wParam, IntPtr lParam);
	// ************************************************************************

	//
	//		//This is the Import for the SetWindowsHookEx function.
	//		//Use this function to install a thread-specific hook.
	//		[DllImport("user32.dll",CharSet=CharSet.Auto,
	//			 CallingConvention=CallingConvention.StdCall)]
	//		protected static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn,
	//			IntPtr hInstance, int threadId);
	//
	//		//This is the Import for the UnhookWindowsHookEx function.
	//		//Call this function to uninstall the hook.
	//		[DllImport("user32.dll",CharSet=CharSet.Auto,
	//			 CallingConvention=CallingConvention.StdCall)]
	//		protected static extern bool UnhookWindowsHookEx(int idHook);
	//
	//		//This is the Import for the CallNextHookEx function.
	//		//Use this function to pass the hook information to the next hook procedure in chain.
	//		[DllImport("user32.dll",CharSet=CharSet.Auto,
	//			 CallingConvention=CallingConvention.StdCall)]
	//		protected static extern int CallNextHookEx(int idHook, int nCode,
	//			IntPtr wParam, IntPtr lParam);

	#endregion

	}
	#endregion
}
